package com.cqsd.ioc.handler;

import com.cqsd.ioc.exception.HandleAddException;
import com.cqsd.result.Result;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiConsumer;

/**
 * @author caseycheng
 * @date 2023/3/11-13:10
 **/
public class AnnotationHandler {
    private final Map<Class<? extends Annotation>, BiConsumer<Annotation, Object>> annotationHandlerMap = new HashMap<>();
    private static final Logger log = LogManager.getLogger(AnnotationHandler.class);

    public void handler(Annotation annotation, Object instance) {
        final BiConsumer<Annotation, Object> h = annotationHandlerMap.get(annotation.annotationType());
        if (h != null) {
            h.accept(annotation, instance);
        }
    }

    public void handler(Annotation[] annotations, Object o) {
        for (Annotation annotation : annotations) {
            final Class<? extends Annotation> annotationType = annotation.annotationType();
            final var h = annotationHandlerMap.get(annotationType);
            if (h != null) {
                h.accept(annotation, o);
            }
        }
    }

    @SuppressWarnings("unchecked")
    public <A extends Annotation> void addHandler(Class<? extends A> type, BiConsumer<? super A, Object> action) {
        //泛型参数 好痛
        Objects.requireNonNull(action);
        if (annotationHandlerMap.containsKey(type)) {
            final var msg = "已有" + type.getSimpleName() + "的处理器请不要重复添加";
            log.error(msg);
            throw new HandleAddException(msg);
        }
        annotationHandlerMap.put(type, (BiConsumer<Annotation, Object>) action);
    }

    /**
     * 获取一个处理器对象
     *
     * @param type
     * @return
     */
    public Result<BiConsumer<Annotation, Object>> getHandler(Class<? extends Annotation> type) {
        Objects.requireNonNull(type);
        final var consumer = annotationHandlerMap.get(type);
        if (consumer != null) {
            return Result.ok(consumer);
        } else {
            return Result.err("没有找到处理器");
        }
    }

    /**
     * 判断是否有对应的注解处理器
     *
     * @param annotation
     * @return
     */
    public boolean isHandler(Class<? extends Annotation> annotation) {
        Objects.requireNonNull(annotation);
        return annotationHandlerMap.containsKey(annotation);
    }

    /**
     * 在注解集合中寻找可用的注解
     *
     * @param annotations
     * @return
     */
    public boolean isHandler(Annotation[] annotations) {
        Objects.requireNonNull(annotations);

        for (Annotation annotation : annotations) {
            if (annotationHandlerMap.containsKey(annotation.annotationType())) {
                return true;
            }
        }
        return false;
    }

    /**
     * 通过输入来决定处理内容
     *
     * @param instance 需要处理的对象
     * @param type     需要处理对象里的什么类型
     */
    public void handlers(Object instance, Class<?> type) {
        if (type.equals(Method.class)) {
            final var methods = instance.getClass().getDeclaredMethods();
            for (Method method : methods) {
                method.setAccessible(true);
                final var annotations = method.getAnnotations();
                for (Annotation annotation : annotations) {
                    handler(annotation, instance);
                }
            }
            return;
        }
        if (type.equals(Field.class)) {

            return;
        }
        if (type.equals(Constructor.class)) {

            return;
        }
        throw new RuntimeException("请指定type为Method｜Field｜Constructor");
    }
}
